﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace MotionCS.Helper
{
    /// <summary>
    /// config文件帮助类
    /// Config文件样式：
    /// [Section]
    /// Key1=Value1
    /// Key2=Value2
    /// ...
    /// </summary>
    public class ConfigHelper : SingleObjectBase<ConfigHelper>
    {
        const string SYSTEM_CONFIG = @"./Config/init.conf";
        const string USER_CONFIG = @"./user_data/usr.conf";

        /// <summary>
        /// Section集合
        /// </summary>
        private List<ConfigSection> _sections;

        /// <summary>
        /// 文件路径
        /// </summary>
        private string _fileName;
        /// <summary>
        /// 保存标志
        /// </summary>
        private bool _isSave = false;
        public bool IsSave
        {
            get => this._isSave;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        public ConfigHelper()
        {
            this._sections = new List<ConfigSection>();
        }

        public void Init()
        {
            if (!File.Exists(SYSTEM_CONFIG))
            {
                Directory.CreateDirectory(@"./Config");
            }
            this._sections.Clear();
            // 先加载一次系统标准配置
            this.LoadFromFile(SYSTEM_CONFIG);
            // 再加载一次用户配置
            //this.LoadFromFile(USER_CONFIG);
        }

        /// <summary>
        /// 从文件加载配置信息
        /// </summary>
        /// <param name="fileName">文件路径</param>
        public void LoadFromFile(string fileName)
        {
            this.LoadFromFile(fileName, Encoding.UTF8);
        }

        /// <summary>
        /// 从文件加载配置信息
        /// </summary>
        /// <param name="fileName">文件路径</param>
        /// <param name="encoding">编码类型</param>
        public void LoadFromFile(string fileName, Encoding encoding)
        {
            this._fileName = fileName;
            if (!File.Exists(this._fileName)) return;

            string[] configs = File.ReadAllLines(this._fileName, encoding);
            string sectionName = string.Empty;
            foreach (string config in configs)
            {
                if (config.StartsWith("[") && config.EndsWith("]"))
                {
                    sectionName = config.TrimStart('[').TrimEnd(']');
                }
                else if (!string.IsNullOrEmpty(sectionName))
                {
                    string[] splitStr = config.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
                    if (splitStr.Length != 2) continue;
                    this.Add(sectionName, splitStr[0], splitStr[1]);
                }
                else
                {
                    sectionName = string.Empty;
                }
            }
        }

        /// <summary>
        /// 添加Section下的Key-Value
        /// </summary>
        /// <param name="section">section的名字</param>
        /// <param name="key">关键字</param>
        /// <param name="value">值</param>
        public void Add(string section, string key, string value)
        {
            var sectionObj = this._sections.Find((s) => { return s.Name.Equals(section); });
            if (sectionObj == null)
            {
                sectionObj = new ConfigSection(section);
                this._sections.Add(sectionObj);
            }
            var contentObj = sectionObj.Contents.Find((c) => { return c.Key.Equals(key); });
            if (contentObj == null)
                sectionObj.Contents.Add(new ConfigContent() { Key = key, Value = value, Section = sectionObj });
            else
                UpdateContent(section, key, value);
        }

        /// <summary>
        /// 删除整个Section的信息
        /// </summary>
        /// <param name="section">section的名字</param>
        /// <returns>true=成功，false=失败</returns>
        public bool RemoveSection(string section)
        {
            bool result = true;
            var sectionObj = this._sections.Find((s) => { return s.Name.Equals(section); });
            if (sectionObj != null)
            {
                result = this._sections.Remove(sectionObj);
            }
            return result;
        }

        /// <summary>
        /// 删除指定Section下的对应key的配置
        /// </summary>
        /// <param name="section">Section名</param>
        /// <param name="key">关键字</param>
        /// <returns>true=成功，false=失败</returns>
        public bool RemoveContent(string section, string key)
        {
            bool result = true;
            var sectionObj = this._sections.Find((s) => { return s.Name.Equals(section); });
            if (sectionObj != null)
            {
                var contentObj = sectionObj.Contents.Find((c) => { return c.Key.Equals(key); });
                if (contentObj != null)
                {
                    result = sectionObj.Contents.Remove(contentObj);
                }
            }
            return result;
        }

        /// <summary>
        /// 查找指定Section下关键字的值
        /// </summary>
        /// <param name="section">Section名</param>
        /// <param name="key">关键字</param>
        /// <returns>关键字对应的值，没找到返回空字符串</returns>
        public string GetValue(string section, string key)
        {
            var sectionObj = this._sections.Find((s) => { return s.Name.Equals(section); });
            if (sectionObj != null)
            {
                var contentObj = sectionObj.Contents.Find((c) => { return c.Key.Equals(key); });
                if (contentObj != null)
                    return contentObj.Value;
            }
            return string.Empty;
        }

        /// <summary>
        /// 查找指定section下关键字的值
        /// </summary>
        /// <param name="section">section名</param>
        /// <param name="key">关键字</param>
        /// <param name="defVal">默认值</param>
        /// <returns>关键字对应的值，没有找到设置为默认值并返回</returns>
        public string GetValue(string section, string key, string defVal)
        {
            string strVal = this.GetValue(section, key);

            if (strVal != string.Empty)
            {
                return strVal;
            }
            else
            {
                this.Add(section, key, defVal);
                this._isSave = true;
                return defVal;
            }
        }

        /// <summary>
        /// 修改指定Section下的对应关键字的值
        /// </summary>
        /// <param name="section">Section名</param>
        /// <param name="key">关键字</param>
        /// <param name="value">修改的值</param>
        public void UpdateContent(string section, string key, string value)
        {
            var sectionObj = this._sections.Find((s) => { return s.Name.Equals(section); });
            if (sectionObj != null)
            {
                var contentObj = sectionObj.Contents.Find((c) => { return c.Key.Equals(key); });
                if (contentObj != null)
                {
                    contentObj.Value = value;
                }
            }
        }

        /// <summary>
        /// 将内存数据写会指定文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public bool WriteToFile(string fileName = null)
        {
            try
            {
                if (string.IsNullOrEmpty(fileName))
                {
                    fileName = this._fileName;
                }
                using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write))
                {
                    using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8))
                    {
                        foreach (ConfigSection section in this._sections)
                        {
                            sw.WriteLine(string.Format("[{0}]", section.Name));
                            foreach (ConfigContent content in section.Contents)
                            {
                                sw.WriteLine(string.Format("{0}={1}", content.Key, content.Value));
                            }
                        }
                    }
                    //fs.Flush();
                }
                this._isSave = false;
            }
            catch (Exception ex)
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// 配置的区域对象
        /// </summary>
        class ConfigSection
        {
            /// <summary>
            /// 区域名
            /// </summary>
            public string Name { get; set; }
            /// <summary>
            /// 区域下对应的键值对
            /// </summary>
            public List<ConfigContent> Contents { get; set; }

            /// <summary>
            /// 构造函数
            /// </summary>
            /// <param name="name">区域名</param>
            public ConfigSection(string name)
            {
                this.Name = name;
                this.Contents = new List<ConfigContent>();
            }
        }

        /// <summary>
        /// 配置的键值对
        /// </summary>
        class ConfigContent
        {
            /// <summary>
            /// 关键字
            /// </summary>
            public string Key { get; set; }
            /// <summary>
            /// 值
            /// </summary>
            public string Value { get; set; }
            /// <summary>
            /// 所属区域
            /// </summary>
            public ConfigSection Section { get; set; }
        }
    }
}
